package chapter3;

/**
 * public interface is used by who using your class
 * protected interface is used by who extending your class
 * @author wei
 *
 */
abstract class SortDouble {
    private double[] values;
    private final SortMetrics curMetrics = new SortMetrics();
    
   /**
    * define the main flow and logic
    * @param data
    * @return
    */
    public final SortMetrics sort(double[] data){
        values = data;
        curMetrics.init();
        doSort();
        return getMetrics();
    }
    
    public final SortMetrics getMetrics(){
        return curMetrics.clone();
    }
    
    /**
     * for extended classes to know the number of elements
     * @return
     */
    protected final int getDataLength(){
        return values.length;
    }
    
    /**
     * for extended classes to probe elements
     * @param i element index
     * @return
     */
    protected final double probe(int i){
        curMetrics.probeCnt++;
        return values[i];
    }
    
    /**
     * for extended class to compare elements
     * @param i element index, not value self
     * @param j element index
     * @return
     */
    protected final int compare(int i, int j){
        curMetrics.compareCnt++;
        double d1 = values[i];
        double d2 = values[j];
        if(d1 == d2){
            return 0;
        }else{
            return (d1 < d2 ? -1 : 1);
        }
    }
    
    /**
     * for extended classes to swap elements
     * @param i
     * @param j
     */
    protected final void swap(int i, int j){
        curMetrics.swapCnt++;
        double tmp = values[i];
        values[i] = values[j];
        values[j] = tmp;
    }
    
    /**
     * extended classes implement this -- used by sort;
     * make it protected to force the test code to invoke it indirectly by the public sort method
     */
    protected abstract void doSort();
}
